package com.minimalist.common.feign.config;

import com.minimalist.common.config.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.UUID;

/**
 * Feign 客户端降级基类
 *
 * @author minimalist
 */
public abstract class BaseFeignClientFallback {

    @Autowired(required = false)
    private ApplicationEventPublisher eventPublisher;

    private static final Logger log = LoggerFactory.getLogger(
            BaseFeignClientFallback.class);

    /**
     * 记录服务调用失败日志，包含请求参数和异常信息
     *
     * @param serviceName 服务名称
     * @param params      请求参数
     * @param cause       异常原因
     */
    protected void logServiceUnavailable(String serviceName, Object params, Throwable cause) {
        String degradeId = UUID.randomUUID().toString();
        MDC.put("degradeId", degradeId);

        try {
            String causeMessage = cause != null ? cause.getClass().getSimpleName() + ": " + cause.getMessage() : "未知原因";

            log.error("{}服务不可用，触发降级，降级ID: {}，原因: {}，参数: {}",
                    serviceName, degradeId, causeMessage, params);

            // 发布降级事件，可用于统计和监控
            if (eventPublisher != null) {
                FeignDegradeEvent event = new FeignDegradeEvent(this, serviceName, params, degradeId, cause);
                eventPublisher.publishEvent(event);
            }
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        } finally {
            MDC.remove("degradeId");
        }
    }

    /**
     * 记录服务调用失败日志，包含请求参数
     *
     * @param serviceName 服务名称
     * @param params      请求参数
     */
    protected void logServiceUnavailable(String serviceName, Object params) {
        // 尝试从当前请求上下文中获取异常
        Throwable cause = extractExceptionFromRequest();
        logServiceUnavailable(serviceName, params, cause);
    }

    /**
     * 记录服务调用失败日志，不包含参数
     *
     * @param serviceName 服务名称
     */
    protected void logServiceUnavailable(String serviceName) {
        // 尝试从当前请求上下文中获取异常
        Throwable cause = extractExceptionFromRequest();
        logServiceUnavailable(serviceName, null, cause);
    }

    /**
     * 从请求上下文中提取异常
     */
    private Throwable extractExceptionFromRequest() {
        try {
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes != null) {
                Object exception = requestAttributes.getAttribute("exception", RequestAttributes.SCOPE_REQUEST);
                if (exception instanceof Throwable) {
                    return (Throwable) exception;
                }
            }
        } catch (Exception e) {
            log.debug("从请求上下文提取异常失败", e);
        }
        return null;
    }
}